const express = require('express');
const https = require('https');
const http = require('http');
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
const multer = require('multer');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const swaggerUi = require('swagger-ui-express');
const swaggerJsdoc = require('swagger-jsdoc');
const net = require('net');
const url = require('url');

// 常量定义
const SUCCESS_CODE = 200;

// ==================== 日志工具函数 ====================

// 日志级别
const LOG_LEVEL = {
  ERROR: '❌ ERROR',
  WARN: '⚠️  WARN',
  INFO: 'ℹ️  INFO',
  DEBUG: '🔍 DEBUG'
};

// 格式化时间戳
function getTimestamp() {
  return new Date().toISOString();
}

// 统一日志输出函数
function log(level, message, data = null) {
  const timestamp = getTimestamp();
  const logMessage = `[${timestamp}] ${level}: ${message}`;
  
  console.log(logMessage);
  
  if (data) {
    if (data instanceof Error) {
      console.log('  Stack:', data.stack);
    } else {
      console.log('  Data:', JSON.stringify(data, null, 2));
    }
  }
  
  // 写入日志文件
  try {
    const logDir = path.join(__dirname, 'logs');
    if (!fs.existsSync(logDir)) {
      fs.mkdirSync(logDir, { recursive: true });
    }
    
    const logFile = path.join(logDir, 'server.log');
    const logEntry = data ? `${logMessage}\n${JSON.stringify(data, null, 2)}\n` : `${logMessage}\n`;
    
    fs.appendFileSync(logFile, logEntry);
  } catch (err) {
    console.error('写入日志文件失败:', err.message);
  }
}

// 快捷日志方法
const logger = {
  error: (msg, data) => log(LOG_LEVEL.ERROR, msg, data),
  warn: (msg, data) => log(LOG_LEVEL.WARN, msg, data),
  info: (msg, data) => log(LOG_LEVEL.INFO, msg, data),
  debug: (msg, data) => log(LOG_LEVEL.DEBUG, msg, data)
};

// ==================== Swagger 配置 ====================

// 动态生成服务器地址的函数
function getServers(host) {
  const hostname = host ? host.split(':')[0] : 'localhost';
  return [
    {
      url: `http://${hostname}:4000`,
      description: 'HTTP 服务器',
    },
    {
      url: `https://${hostname}:4001`,
      description: 'HTTPS 服务器（基础TLS）',
    },
    {
      url: `https://${hostname}:4002`,
      description: 'HTTPS 双向认证（带密码）',
    },
    {
      url: `https://${hostname}:4003`,
      description: 'HTTPS 双向认证（无密码）',
    },
    {
      url: `https://${hostname}:4004`,
      description: 'HTTPS（TLS 1.2）',
    },
    {
      url: `https://${hostname}:4005`,
      description: 'HTTP/2 服务器',
    },
  ];
}

const swaggerOptions = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'OHOS Axios Test Server API',
      version: '2.0.0',
      description: 'OpenHarmony HTTP/HTTPS 测试服务器 API 文档 - 支持多种 HTTP 方法、TLS 配置、文件操作和证书管理',
      contact: {
        name: 'OHOS Test Server',
      },
      license: {
        name: 'MIT',
        url: 'https://opensource.org/licenses/MIT',
      },
    },
    servers: getServers('localhost'),  // 默认值，会被动态替换
    tags: [
      {
        name: 'Basic',
        description: '基础 HTTP 请求操作',
      },
      {
        name: 'Files',
        description: '文件上传和下载',
      },
      {
        name: 'Certificates',
        description: '证书下载和管理',
      },
    ],
    components: {
      schemas: {
        SuccessResponse: {
          type: 'object',
          properties: {
            method: {
              type: 'string',
              example: 'GET',
            },
            message: {
              type: 'string',
              example: 'Request successful',
            },
            timestamp: {
              type: 'string',
              format: 'date-time',
              example: '2025-11-25T10:00:00.000Z',
            },
          },
        },
        ErrorResponse: {
          type: 'object',
          properties: {
            error: {
              type: 'string',
              example: 'Error message',
            },
            message: {
              type: 'string',
              example: 'Detailed error description',
            },
          },
        },
      },
    },
  },
  apis: ['./server.js'], // 扫描当前文件的注释
};

const swaggerSpec = swaggerJsdoc(swaggerOptions);

// 配置文件上传
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    const uploadDir = path.join(__dirname, 'upload');
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    cb(null, uploadDir);
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname);
  }
});

const upload = multer({ storage: storage });

// 创建 Express 应用
const app = express();

// 中间件
app.use(cors());

// Body parser 中间件（带错误处理）
app.use(bodyParser.json({
  limit: '10mb',
  verify: (req, res, buf, encoding) => {
    try {
      JSON.parse(buf);
    } catch (e) {
      logger.warn('JSON解析失败', { error: e.message, body: buf.toString() });
    }
  }
}));

app.use(bodyParser.urlencoded({ 
  extended: true,
  limit: '10mb'
}));

app.use(morgan('combined'));
app.use('/public', express.static(path.join(__dirname, 'public')));

// 请求日志中间件
app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    const duration = Date.now() - start;
    logger.info(`${req.method} ${req.path} - ${res.statusCode} (${duration}ms)`);
  });
  next();
});

// 全局错误捕获中间件（必须在所有路由之后）
const errorHandler = (err, req, res, next) => {
  logger.error('请求处理错误', {
    error: err.message,
    stack: err.stack,
    method: req.method,
    path: req.path,
    query: req.query,
    body: req.body
  });
  
  // 防止重复发送响应
  if (res.headersSent) {
    return next(err);
  }
  
  res.status(err.status || 500).json({
    error: 'Internal Server Error',
    message: err.message || 'An unexpected error occurred',
    timestamp: new Date().toISOString(),
    path: req.path
  });
};

// 异步路由包装器 - 自动捕获异步错误
const asyncHandler = (fn) => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

// 动态生成 Swagger Spec（根据请求的 host）
function getDynamicSwaggerSpec(host) {
  const spec = JSON.parse(JSON.stringify(swaggerSpec)); // 深拷贝
  spec.servers = getServers(host);
  return spec;
}

// Swagger UI - 使用动态配置
app.use('/api-docs', swaggerUi.serve);
app.get('/api-docs', (req, res, next) => {
  const dynamicSpec = getDynamicSwaggerSpec(req.headers.host);
  return swaggerUi.setup(dynamicSpec, {
    customCss: '.swagger-ui .topbar { display: none }',
    customSiteTitle: 'OHOS Test Server API',
  })(req, res, next);
});

// Swagger JSON - 动态返回
app.get('/api-docs.json', (req, res) => {
  const dynamicSpec = getDynamicSwaggerSpec(req.headers.host);
  res.setHeader('Content-Type', 'application/json');
  res.send(dynamicSpec);
});

// ==================== 路由定义 ====================

/**
 * @swagger
 * /:
 *   get:
 *     summary: 服务器主页
 *     description: 返回服务器信息和可用端点列表
 *     tags: [Basic]
 *     responses:
 *       200:
 *         description: HTML 格式的服务器信息页面
 *         content:
 *           text/html:
 *             schema:
 *               type: string
 */
// 主页
app.get('/', (req, res) => {
  res.send(`
    <html>
      <head><title>OHOS Axios Test Server</title></head>
      <body>
        <h1>🚀 OpenHarmony HTTP/HTTPS 测试服务器</h1>
        <h2>可用端点：</h2>
        <ul>
          <li><a href="/tpc/get">GET /tpc/get</a></li>
          <li>POST /tpc/post</li>
          <li>PUT /tpc/put</li>
          <li>PATCH /tpc/patch</li>
          <li>DELETE /tpc/delete</li>
          <li><a href="/tpc/getDelay">GET /tpc/getDelay</a> (8秒延迟)</li>
          <li><a href="/tpc/redirect">GET /tpc/redirect</a> (重定向)</li>
          <li><a href="/tpc/getGzip">GET /tpc/getGzip</a> (GZIP压缩响应)</li>
          <li>POST /tpc/postGzip (GZIP压缩响应)</li>
          <li>POST /tpc/upload (文件上传)</li>
          <li><a href="/tpc/download">GET /tpc/download</a> (下载第一个文件)</li>
          <li><a href="/upload">GET /upload</a> (列出已上传文件 JSON)</li>
          <li>GET /upload/:filename (下载指定文件)</li>
          <li><a href="/files">📁 文件管理页面</a> (上传/下载/删除)</li>
        </ul>
        <h2>📜 证书下载：</h2>
        <h4>🔓 无密码版本（用于 4003 端口）</h4>
        <ul>
          <li><a href="/cert/ca.crt">GET /cert/ca.crt</a> (CA根证书 - 信任服务器)</li>
          <li><a href="/cert/server.crt">GET /cert/server.crt</a> (服务器证书)</li>
          <li><a href="/cert/client.crt">GET /cert/client.crt</a> (客户端证书)</li>
          <li><a href="/cert/client.key">GET /cert/client.key</a> (客户端私钥 - 无密码)</li>
          <li><a href="/cert/client.p12">GET /cert/client.p12</a> (P12证书包 - 无密码)</li>
        </ul>
        <h4>🔐 带密码版本（用于 4002 端口，密码: 123456）</h4>
        <ul>
          <li><a href="/cert/client_encrypted.key">GET /cert/client_encrypted.key</a> (客户端私钥 - 密码: 123456)</li>
          <li><a href="/cert/client_encrypted.p12">GET /cert/client_encrypted.p12</a> (P12证书包 - 密码: 123456)</li>
        </ul>
        <h4>📦 其他</h4>
        <ul>
          <li><a href="/cert/client-bundle">GET /cert/client-bundle</a> (一键获取所有证书 JSON)</li>
          <li><a href="/cert/list">GET /cert/list</a> (证书列表和状态)</li>
        </ul>
        <p style="color: #666; font-size: 14px;">
          💡 提示：4002 端口需使用带密码的证书（client_encrypted.key 或 client_encrypted.p12）<br>
          💡 提示：4003 端口使用无密码的证书（client.key 或 client.p12）
        </p>
        <h2>📖 API 文档：</h2>
        <ul>
          <li><a href="/api-docs" target="_blank">🔗 Swagger UI 交互式文档</a></li>
          <li><a href="/api-docs.json" target="_blank">📄 OpenAPI JSON 规范</a></li>
        </ul>
        <h3>服务器信息：</h3>
        <ul>
          <li>HTTP 端口: 4000</li>
          <li>HTTPS 基础端口: 4001（单向认证）</li>
          <li>HTTPS 双向认证端口: 4002（使用 client_encrypted.key/p12，密码: 123456）</li>
          <li>HTTPS 双向认证端口: 4003（使用 client.key/p12，无密码）</li>
          <li>HTTPS TLS 1.2 端口: 4004</li>
          <li>HTTP/2 端口: 4005</li>
        </ul>
        <h3>🔌 代理服务器：</h3>
        <ul>
          <li><strong>SOCKS5 代理:</strong> 端口 1080（无认证）
            <ul style="color: #666; font-size: 14px;">
              <li>支持 TCP 连接代理</li>
              <li>支持 IPv4/IPv6/域名地址</li>
              <li>适用于任何 TCP 协议（HTTP/HTTPS/FTP等）</li>
            </ul>
          </li>
          <li><strong>HTTP/HTTPS 代理:</strong> 端口 8080（无认证）
            <ul style="color: #666; font-size: 14px;">
              <li>支持 HTTP 请求代理</li>
              <li>支持 HTTPS CONNECT 隧道</li>
              <li>无需用户名密码</li>
            </ul>
          </li>
          <li><strong>HTTP/HTTPS 代理:</strong> 端口 8081（需认证）
            <ul style="color: #666; font-size: 14px;">
              <li>用户名: <code>admin</code></li>
              <li>密码: <code>123456</code></li>
              <li>使用 Basic 认证方式</li>
            </ul>
          </li>
        </ul>
        <p style="color: #666; font-size: 14px;">
          💡 代理配置示例：<br>
          &nbsp;&nbsp;• SOCKS5: socks5://localhost:1080<br>
          &nbsp;&nbsp;• HTTP（无认证）: http://localhost:8080<br>
          &nbsp;&nbsp;• HTTP（需认证）: http://admin:123456@localhost:8081
        </p>
      </body>
    </html>
  `);
});

/**
 * @swagger
 * /tpc/get:
 *   get:
 *     summary: GET 请求测试
 *     description: 测试 GET 请求，返回查询参数和请求头
 *     tags: [Basic]
 *     parameters:
 *       - in: query
 *         name: param1
 *         schema:
 *           type: string
 *         description: 测试查询参数
 *     responses:
 *       200:
 *         description: 成功响应
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 method:
 *                   type: string
 *                   example: GET
 *                 message:
 *                   type: string
 *                   example: GET request successful
 *                 timestamp:
 *                   type: string
 *                   format: date-time
 *                 query:
 *                   type: object
 *                 headers:
 *                   type: object
 */
// GET 请求
app.get('/tpc/get', (req, res) => {
  res.json({
    method: 'GET',
    message: 'GET request successful',
    timestamp: new Date().toISOString(),
    query: req.query,
    headers: req.headers
  });
});

/**
 * @swagger
 * /tpc/post:
 *   post:
 *     summary: POST 请求测试
 *     description: 测试 POST 请求，返回请求体和请求头
 *     tags: [Basic]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               data:
 *                 type: string
 *                 example: test data
 *     responses:
 *       200:
 *         description: 成功响应
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/SuccessResponse'
 */
// POST 请求
app.post('/tpc/post', (req, res) => {
  res.json({
    method: 'POST',
    message: 'POST request successful',
    timestamp: new Date().toISOString(),
    body: req.body,
    headers: req.headers
  });
});

/**
 * @swagger
 * /tpc/put:
 *   put:
 *     summary: PUT 请求测试
 *     description: 测试 PUT 请求，返回请求体和请求头
 *     tags: [Basic]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *     responses:
 *       200:
 *         description: 成功响应
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/SuccessResponse'
 */
// PUT 请求
app.put('/tpc/put', (req, res) => {
  res.json({
    method: 'PUT',
    message: 'PUT request successful',
    timestamp: new Date().toISOString(),
    body: req.body,
    headers: req.headers
  });
});

/**
 * @swagger
 * /tpc/patch:
 *   patch:
 *     summary: PATCH 请求测试
 *     description: 测试 PATCH 请求，用于部分更新资源
 *     tags: [Basic]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *     responses:
 *       200:
 *         description: 成功响应
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/SuccessResponse'
 */
// PATCH 请求
app.patch('/tpc/patch', (req, res) => {
  res.json({
    method: 'PATCH',
    message: 'PATCH request successful',
    timestamp: new Date().toISOString(),
    body: req.body,
    headers: req.headers
  });
});

/**
 * @swagger
 * /tpc/delete:
 *   delete:
 *     summary: DELETE 请求测试
 *     description: 测试 DELETE 请求，返回查询参数
 *     tags: [Basic]
 *     parameters:
 *       - in: query
 *         name: id
 *         schema:
 *           type: string
 *         description: 要删除的资源ID
 *     responses:
 *       200:
 *         description: 成功响应
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/SuccessResponse'
 */
// DELETE 请求
app.delete('/tpc/delete', (req, res) => {
  res.json({
    method: 'DELETE',
    message: 'DELETE request successful',
    timestamp: new Date().toISOString(),
    query: req.query,
    headers: req.headers
  });
});

/**
 * @swagger
 * /tpc/getDelay:
 *   get:
 *     summary: 延迟响应测试
 *     description: 测试延迟响应，8秒后返回结果（用于测试超时处理）
 *     tags: [Basic]
 *     responses:
 *       200:
 *         description: 延迟8秒后的成功响应
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 method:
 *                   type: string
 *                   example: GET
 *                 message:
 *                   type: string
 *                   example: Delayed response after 8 seconds
 *                 timestamp:
 *                   type: string
 *                   format: date-time
 *                 delay:
 *                   type: string
 *                   example: 8000ms
 */
// 延迟响应 (8秒)
app.get('/tpc/getDelay', (req, res) => {
  setTimeout(() => {
    res.json({
      method: 'GET',
      message: 'Delayed response after 8 seconds',
      timestamp: new Date().toISOString(),
      delay: '8000ms'
    });
  }, 8000);
});

/**
 * @swagger
 * /tpc/redirect:
 *   get:
 *     summary: 重定向测试
 *     description: 测试 HTTP 重定向，会重定向到 /tpc/get
 *     tags: [Basic]
 *     responses:
 *       302:
 *         description: 重定向到 /tpc/get
 */
// 重定向
app.get('/tpc/redirect', (req, res) => {
  res.redirect('/tpc/get');
});

/**
 * @swagger
 * /tpc/getGzip:
 *   get:
 *     summary: GZIP 压缩 GET 请求测试
 *     description: 返回经过 GZIP 压缩的 JSON 响应，用于测试客户端的 GZIP 解压能力
 *     tags: [Basic]
 *     responses:
 *       200:
 *         description: GZIP 压缩的 JSON 响应
 *         headers:
 *           Content-Encoding:
 *             schema:
 *               type: string
 *               example: gzip
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 code:
 *                   type: integer
 *                   example: 200
 *                 data:
 *                   type: string
 *                   example: 这是一个经过GZIP压缩的GET请求响应。
 *                 msg:
 *                   type: string
 *                   example: GZIP压缩成功
 */
// GZIP 压缩 GET 请求
app.get('/tpc/getGzip', (req, res) => {
  const data = {
    code: SUCCESS_CODE,
    data: '这是一个经过GZIP压缩的GET请求响应。',
    msg: 'GZIP压缩成功',
  };

  const jsonString = JSON.stringify(data);
  const inputBuffer = Buffer.from(jsonString, 'utf8');
  const compressedBuffer = zlib.gzipSync(inputBuffer);

  res.writeHead(200, {
    'Content-Type': 'application/json; charset=utf-8',
    'Content-Encoding': 'gzip',
    'Content-Length': compressedBuffer.length,
  });

  res.end(compressedBuffer);
});

/**
 * @swagger
 * /tpc/postGzip:
 *   post:
 *     summary: GZIP 压缩 POST 请求测试
 *     description: 返回经过 GZIP 压缩的 JSON 响应，用于测试客户端的 GZIP 解压能力
 *     tags: [Basic]
 *     requestBody:
 *       required: false
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *     responses:
 *       200:
 *         description: GZIP 压缩的 JSON 响应
 *         headers:
 *           Content-Encoding:
 *             schema:
 *               type: string
 *               example: gzip
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 code:
 *                   type: integer
 *                   example: 200
 *                 data:
 *                   type: string
 *                   example: 这是一个经过GZIP压缩的POST请求响应。
 *                 msg:
 *                   type: string
 *                   example: GZIP压缩成功
 */
// GZIP 压缩 POST 请求
app.post('/tpc/postGzip', (req, res) => {
  const data = {
    code: SUCCESS_CODE,
    data: '这是一个经过GZIP压缩的POST请求响应。',
    msg: 'GZIP压缩成功',
  };

  const jsonString = JSON.stringify(data);
  const inputBuffer = Buffer.from(jsonString, 'utf8');
  const compressedBuffer = zlib.gzipSync(inputBuffer);

  res.writeHead(200, {
    'Content-Type': 'application/json; charset=utf-8',
    'Content-Encoding': 'gzip',
    'Content-Length': compressedBuffer.length,
  });

  res.end(compressedBuffer);
});

/**
 * @swagger
 * /tpc/upload:
 *   post:
 *     summary: 文件上传
 *     description: 上传文件到服务器
 *     tags: [Files]
 *     requestBody:
 *       required: true
 *       content:
 *         multipart/form-data:
 *           schema:
 *             type: object
 *             properties:
 *               file:
 *                 type: string
 *                 format: binary
 *                 description: 要上传的文件
 *     responses:
 *       200:
 *         description: 文件上传成功
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 method:
 *                   type: string
 *                   example: POST
 *                 message:
 *                   type: string
 *                   example: File uploaded successfully
 *                 timestamp:
 *                   type: string
 *                   format: date-time
 *                 file:
 *                   type: object
 *                   properties:
 *                     originalname:
 *                       type: string
 *                     filename:
 *                       type: string
 *                     size:
 *                       type: number
 *                     path:
 *                       type: string
 *       400:
 *         description: 没有文件上传
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/ErrorResponse'
 */
// 文件上传
app.post('/tpc/upload', upload.single('file'), (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }
  
  res.json({
    method: 'POST',
    message: 'File uploaded successfully',
    timestamp: new Date().toISOString(),
    file: {
      originalname: req.file.originalname,
      filename: req.file.filename,
      size: req.file.size,
      path: req.file.path
    }
  });
});

/**
 * @swagger
 * /tpc/download:
 *   get:
 *     summary: 文件下载
 *     description: 下载上传目录中的第一个文件
 *     tags: [Files]
 *     responses:
 *       200:
 *         description: 文件下载成功
 *         content:
 *           application/octet-stream:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 没有可下载的文件
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/ErrorResponse'
 */
// 文件下载
app.get('/tpc/download', (req, res) => {
  const uploadDir = path.join(__dirname, 'upload');
  
  // 检查上传目录是否存在
  if (!fs.existsSync(uploadDir)) {
    return res.status(404).json({ error: 'Upload directory not found' });
  }
  
  // 获取目录中的文件列表
  const files = fs.readdirSync(uploadDir);
  
  if (files.length === 0) {
    return res.status(404).json({ error: 'No files available for download' });
  }
  
  // 下载第一个文件
  const filePath = path.join(uploadDir, files[0]);
  res.download(filePath, files[0], (err) => {
    if (err) {
      console.error('Download error:', err);
      res.status(500).json({ error: 'Download failed' });
    }
  });
});

/**
 * @swagger
 * /upload/{filename}:
 *   get:
 *     summary: 下载指定文件
 *     description: 下载上传目录中指定文件名的文件
 *     tags: [Files]
 *     parameters:
 *       - in: path
 *         name: filename
 *         required: true
 *         schema:
 *           type: string
 *         description: 要下载的文件名
 *         example: "1732612345678-test.png"
 *     responses:
 *       200:
 *         description: 文件下载成功
 *         content:
 *           application/octet-stream:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 文件不存在
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/ErrorResponse'
 *       400:
 *         description: 非法文件路径
 */
// 下载指定文件
app.get('/upload/:filename', (req, res) => {
  const filename = req.params.filename;
  const uploadDir = path.join(__dirname, 'upload');
  const filePath = path.join(uploadDir, filename);
  
  // 安全检查：防止路径遍历攻击
  const resolvedPath = path.resolve(filePath);
  const resolvedUploadDir = path.resolve(uploadDir);
  
  if (!resolvedPath.startsWith(resolvedUploadDir)) {
    return res.status(400).json({ 
      error: 'Invalid file path',
      message: '非法的文件路径'
    });
  }
  
  // 检查文件是否存在
  if (!fs.existsSync(filePath)) {
    return res.status(404).json({ 
      error: 'File not found',
      message: `文件 "${filename}" 不存在`,
      hint: '请先上传文件到 /tpc/upload'
    });
  }
  
  // 获取文件信息
  const stat = fs.statSync(filePath);
  
  // 检查是否是文件（不是目录）
  if (!stat.isFile()) {
    return res.status(400).json({ 
      error: 'Not a file',
      message: '请求的路径不是文件'
    });
  }
  
  // 下载文件
  res.download(filePath, filename, (err) => {
    if (err) {
      console.error('Download error:', err);
      if (!res.headersSent) {
        res.status(500).json({ error: 'Download failed' });
      }
    }
  });
});

/**
 * @swagger
 * /upload:
 *   get:
 *     summary: 列出所有已上传的文件
 *     description: 获取上传目录中所有文件的列表
 *     tags: [Files]
 *     responses:
 *       200:
 *         description: 文件列表
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 message:
 *                   type: string
 *                   example: 已上传的文件列表
 *                 files:
 *                   type: array
 *                   items:
 *                     type: object
 *                     properties:
 *                       filename:
 *                         type: string
 *                       size:
 *                         type: number
 *                       downloadUrl:
 *                         type: string
 *                       uploadTime:
 *                         type: string
 */
// 列出所有已上传的文件
app.get('/upload', (req, res) => {
  const uploadDir = path.join(__dirname, 'upload');
  
  // 检查上传目录是否存在
  if (!fs.existsSync(uploadDir)) {
    return res.json({ 
      message: '已上传的文件列表',
      files: [],
      hint: '上传目录为空，请先上传文件到 /tpc/upload'
    });
  }
  
  // 获取目录中的文件列表
  const files = fs.readdirSync(uploadDir);
  
  const fileList = files.map(filename => {
    const filePath = path.join(uploadDir, filename);
    const stat = fs.statSync(filePath);
    return {
      filename: filename,
      size: stat.size,
      downloadUrl: `/upload/${encodeURIComponent(filename)}`,
      uploadTime: stat.mtime.toISOString()
    };
  });
  
  res.json({
    message: '已上传的文件列表',
    count: fileList.length,
    files: fileList
  });
});

// ==================== 文件管理页面 ====================

/**
 * @swagger
 * /files:
 *   get:
 *     summary: 文件管理页面
 *     description: 显示上传文件夹中的所有文件，支持上传和下载
 *     tags: [Files]
 *     responses:
 *       200:
 *         description: HTML 文件管理页面
 *         content:
 *           text/html:
 *             schema:
 *               type: string
 */
// 文件管理页面
app.get('/files', (req, res) => {
  const uploadDir = path.join(__dirname, 'upload');
  let files = [];
  
  // 获取文件列表
  if (fs.existsSync(uploadDir)) {
    const fileNames = fs.readdirSync(uploadDir);
    files = fileNames.map(filename => {
      const filePath = path.join(uploadDir, filename);
      const stat = fs.statSync(filePath);
      return {
        filename: filename,
        size: stat.size,
        sizeFormatted: formatFileSize(stat.size),
        uploadTime: stat.mtime.toISOString(),
        uploadTimeFormatted: stat.mtime.toLocaleString('zh-CN')
      };
    });
  }
  
  // 生成文件列表 HTML
  const fileListHtml = files.length > 0 
    ? files.map(f => `
        <tr>
          <td class="filename" title="${f.filename}">${f.filename}</td>
          <td>${f.sizeFormatted}</td>
          <td>${f.uploadTimeFormatted}</td>
          <td>
            <a href="/upload/${encodeURIComponent(f.filename)}" class="btn btn-download" download>📥 下载</a>
            <button class="btn btn-delete" onclick="deleteFile('${f.filename}')">🗑️ 删除</button>
          </td>
        </tr>
      `).join('')
    : '<tr><td colspan="4" class="empty">📭 暂无文件，请上传</td></tr>';

  res.send(`
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>文件管理 - OHOS Test Server</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      min-height: 100vh;
      padding: 20px;
    }
    
    .container {
      max-width: 1000px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      color: white;
      margin-bottom: 30px;
    }
    
    .header h1 {
      font-size: 2.5rem;
      margin-bottom: 10px;
      text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
    }
    
    .header p {
      opacity: 0.9;
    }
    
    .card {
      background: white;
      border-radius: 16px;
      box-shadow: 0 10px 40px rgba(0,0,0,0.2);
      overflow: hidden;
      margin-bottom: 20px;
    }
    
    .card-header {
      background: linear-gradient(135deg, #f5f7fa 0%, #e4e8ec 100%);
      padding: 20px;
      border-bottom: 1px solid #eee;
    }
    
    .card-header h2 {
      color: #333;
      font-size: 1.3rem;
    }
    
    .card-body {
      padding: 20px;
    }
    
    /* 上传区域 */
    .upload-area {
      border: 3px dashed #ddd;
      border-radius: 12px;
      padding: 40px;
      text-align: center;
      transition: all 0.3s ease;
      cursor: pointer;
      background: #fafafa;
    }
    
    .upload-area:hover, .upload-area.dragover {
      border-color: #667eea;
      background: #f0f4ff;
    }
    
    .upload-area .icon {
      font-size: 4rem;
      margin-bottom: 15px;
    }
    
    .upload-area p {
      color: #666;
      margin-bottom: 15px;
    }
    
    .upload-area input[type="file"] {
      display: none;
    }
    
    .btn {
      display: inline-block;
      padding: 10px 20px;
      border-radius: 8px;
      text-decoration: none;
      font-weight: 500;
      cursor: pointer;
      border: none;
      transition: all 0.3s ease;
      font-size: 14px;
    }
    
    .btn-primary {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      color: white;
    }
    
    .btn-primary:hover {
      transform: translateY(-2px);
      box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4);
    }
    
    .btn-download {
      background: #28a745;
      color: white;
      margin-right: 8px;
    }
    
    .btn-download:hover {
      background: #218838;
    }
    
    .btn-delete {
      background: #dc3545;
      color: white;
    }
    
    .btn-delete:hover {
      background: #c82333;
    }
    
    /* 文件列表表格 */
    .file-table {
      width: 100%;
      border-collapse: collapse;
    }
    
    .file-table th {
      background: #f8f9fa;
      padding: 15px;
      text-align: left;
      font-weight: 600;
      color: #333;
      border-bottom: 2px solid #dee2e6;
    }
    
    .file-table td {
      padding: 15px;
      border-bottom: 1px solid #eee;
      vertical-align: middle;
    }
    
    .file-table tr:hover {
      background: #f8f9fa;
    }
    
    .file-table .filename {
      max-width: 300px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-family: monospace;
      color: #495057;
    }
    
    .file-table .empty {
      text-align: center;
      color: #999;
      padding: 40px;
    }
    
    /* 进度条 */
    .progress-container {
      display: none;
      margin-top: 20px;
    }
    
    .progress-bar {
      height: 8px;
      background: #e9ecef;
      border-radius: 4px;
      overflow: hidden;
    }
    
    .progress-fill {
      height: 100%;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      width: 0%;
      transition: width 0.3s ease;
    }
    
    .progress-text {
      text-align: center;
      margin-top: 10px;
      color: #666;
    }
    
    /* 消息提示 */
    .message {
      padding: 15px 20px;
      border-radius: 8px;
      margin-bottom: 20px;
      display: none;
    }
    
    .message.success {
      background: #d4edda;
      color: #155724;
      border: 1px solid #c3e6cb;
    }
    
    .message.error {
      background: #f8d7da;
      color: #721c24;
      border: 1px solid #f5c6cb;
    }
    
    /* 统计信息 */
    .stats {
      display: flex;
      gap: 20px;
      margin-bottom: 15px;
    }
    
    .stat-item {
      background: #f8f9fa;
      padding: 10px 20px;
      border-radius: 8px;
    }
    
    .stat-item span {
      font-weight: bold;
      color: #667eea;
    }
    
    /* 返回链接 */
    .back-link {
      display: inline-block;
      color: white;
      text-decoration: none;
      margin-bottom: 20px;
      opacity: 0.9;
    }
    
    .back-link:hover {
      opacity: 1;
    }
    
    @media (max-width: 768px) {
      .header h1 {
        font-size: 1.8rem;
      }
      
      .file-table th, .file-table td {
        padding: 10px;
        font-size: 14px;
      }
      
      .btn {
        padding: 8px 12px;
        font-size: 12px;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <a href="/" class="back-link">← 返回首页</a>
    
    <div class="header">
      <h1>📁 文件管理</h1>
      <p>上传、下载和管理您的文件</p>
    </div>
    
    <div id="message" class="message"></div>
    
    <!-- 上传区域 -->
    <div class="card">
      <div class="card-header">
        <h2>📤 上传文件</h2>
      </div>
      <div class="card-body">
        <div class="upload-area" id="uploadArea">
          <div class="icon">📁</div>
          <p>拖拽文件到此处，或点击选择文件</p>
          <input type="file" id="fileInput" multiple>
          <button class="btn btn-primary" onclick="document.getElementById('fileInput').click()">选择文件</button>
        </div>
        <div class="progress-container" id="progressContainer">
          <div class="progress-bar">
            <div class="progress-fill" id="progressFill"></div>
          </div>
          <div class="progress-text" id="progressText">上传中...</div>
        </div>
      </div>
    </div>
    
    <!-- 文件列表 -->
    <div class="card">
      <div class="card-header">
        <h2>📋 文件列表</h2>
      </div>
      <div class="card-body">
        <div class="stats">
          <div class="stat-item">文件数量: <span>${files.length}</span></div>
          <div class="stat-item">总大小: <span>${formatFileSize(files.reduce((sum, f) => sum + f.size, 0))}</span></div>
        </div>
        <table class="file-table">
          <thead>
            <tr>
              <th>文件名</th>
              <th>大小</th>
              <th>上传时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody id="fileList">
            ${fileListHtml}
          </tbody>
        </table>
      </div>
    </div>
  </div>
  
  <script>
    const uploadArea = document.getElementById('uploadArea');
    const fileInput = document.getElementById('fileInput');
    const progressContainer = document.getElementById('progressContainer');
    const progressFill = document.getElementById('progressFill');
    const progressText = document.getElementById('progressText');
    const messageDiv = document.getElementById('message');
    
    // 显示消息
    function showMessage(text, type) {
      messageDiv.textContent = text;
      messageDiv.className = 'message ' + type;
      messageDiv.style.display = 'block';
      setTimeout(() => {
        messageDiv.style.display = 'none';
      }, 5000);
    }
    
    // 拖拽事件
    uploadArea.addEventListener('dragover', (e) => {
      e.preventDefault();
      uploadArea.classList.add('dragover');
    });
    
    uploadArea.addEventListener('dragleave', () => {
      uploadArea.classList.remove('dragover');
    });
    
    uploadArea.addEventListener('drop', (e) => {
      e.preventDefault();
      uploadArea.classList.remove('dragover');
      const files = e.dataTransfer.files;
      if (files.length > 0) {
        uploadFiles(files);
      }
    });
    
    // 文件选择
    fileInput.addEventListener('change', () => {
      if (fileInput.files.length > 0) {
        uploadFiles(fileInput.files);
      }
    });
    
    // 上传文件
    async function uploadFiles(files) {
      for (let i = 0; i < files.length; i++) {
        await uploadFile(files[i], i + 1, files.length);
      }
      // 刷新页面显示新文件
      setTimeout(() => location.reload(), 500);
    }
    
    async function uploadFile(file, current, total) {
      const formData = new FormData();
      formData.append('file', file);
      
      progressContainer.style.display = 'block';
      progressText.textContent = '上传中: ' + file.name + ' (' + current + '/' + total + ')';
      
      try {
        const xhr = new XMLHttpRequest();
        
        xhr.upload.addEventListener('progress', (e) => {
          if (e.lengthComputable) {
            const percent = Math.round((e.loaded / e.total) * 100);
            progressFill.style.width = percent + '%';
          }
        });
        
        await new Promise((resolve, reject) => {
          xhr.onload = () => {
            if (xhr.status === 200) {
              showMessage('文件 "' + file.name + '" 上传成功！', 'success');
              resolve();
            } else {
              reject(new Error('上传失败'));
            }
          };
          xhr.onerror = () => reject(new Error('网络错误'));
          xhr.open('POST', '/tpc/upload');
          xhr.send(formData);
        });
        
      } catch (error) {
        showMessage('上传失败: ' + error.message, 'error');
      }
      
      progressContainer.style.display = 'none';
      progressFill.style.width = '0%';
    }
    
    // 删除文件
    async function deleteFile(filename) {
      if (!confirm('确定要删除文件 "' + filename + '" 吗？')) {
        return;
      }
      
      try {
        const response = await fetch('/upload/' + encodeURIComponent(filename), {
          method: 'DELETE'
        });
        
        if (response.ok) {
          showMessage('文件已删除', 'success');
          setTimeout(() => location.reload(), 500);
        } else {
          const data = await response.json();
          showMessage('删除失败: ' + data.message, 'error');
        }
      } catch (error) {
        showMessage('删除失败: ' + error.message, 'error');
      }
    }
  </script>
</body>
</html>
  `);
});

// 格式化文件大小
function formatFileSize(bytes) {
  if (bytes === 0) return '0 B';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

// 删除文件接口
app.delete('/upload/:filename', (req, res) => {
  const filename = req.params.filename;
  const uploadDir = path.join(__dirname, 'upload');
  const filePath = path.join(uploadDir, filename);
  
  // 安全检查：防止路径遍历攻击
  const resolvedPath = path.resolve(filePath);
  const resolvedUploadDir = path.resolve(uploadDir);
  
  if (!resolvedPath.startsWith(resolvedUploadDir)) {
    return res.status(400).json({ 
      error: 'Invalid file path',
      message: '非法的文件路径'
    });
  }
  
  // 检查文件是否存在
  if (!fs.existsSync(filePath)) {
    return res.status(404).json({ 
      error: 'File not found',
      message: `文件 "${filename}" 不存在`
    });
  }
  
  try {
    fs.unlinkSync(filePath);
    res.json({ 
      message: '文件删除成功',
      filename: filename
    });
  } catch (error) {
    res.status(500).json({ 
      error: 'Delete failed',
      message: '删除失败: ' + error.message
    });
  }
});

// ==================== 证书下载 API ====================

/**
 * @swagger
 * /cert/ca.crt:
 *   get:
 *     summary: 下载 CA 根证书
 *     description: 下载 CA 根证书用于客户端信任服务器（自签名证书）
 *     tags: [Certificates]
 *     responses:
 *       200:
 *         description: CA 证书文件
 *         content:
 *           application/x-x509-ca-cert:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 证书不存在
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/ErrorResponse'
 */
// 获取 CA 证书（服务器证书即为自签名 CA）
app.get('/cert/ca.crt', (req, res) => {
  const certPath = path.join(__dirname, './cert/server.crt');
  
  if (!fs.existsSync(certPath)) {
    return res.status(404).json({ 
      error: 'CA certificate not found',
      message: '证书文件不存在，请先运行服务器生成证书'
    });
  }
  
  res.setHeader('Content-Type', 'application/x-x509-ca-cert');
  res.setHeader('Content-Disposition', 'attachment; filename="ca.crt"');
  res.sendFile(certPath);
});

/**
 * @swagger
 * /cert/server.crt:
 *   get:
 *     summary: 下载服务器证书
 *     description: 下载服务器 SSL/TLS 证书
 *     tags: [Certificates]
 *     responses:
 *       200:
 *         description: 服务器证书文件
 *         content:
 *           application/x-x509-ca-cert:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 证书不存在
 */
// 获取服务器证书
app.get('/cert/server.crt', (req, res) => {
  const certPath = path.join(__dirname, './cert/server.crt');
  
  if (!fs.existsSync(certPath)) {
    return res.status(404).json({ 
      error: 'Server certificate not found',
      message: '证书文件不存在'
    });
  }
  
  res.setHeader('Content-Type', 'application/x-x509-ca-cert');
  res.setHeader('Content-Disposition', 'attachment; filename="server.crt"');
  res.sendFile(certPath);
});

/**
 * @swagger
 * /cert/client.crt:
 *   get:
 *     summary: 下载客户端证书
 *     description: 下载客户端证书用于双向认证
 *     tags: [Certificates]
 *     responses:
 *       200:
 *         description: 客户端证书文件
 *         content:
 *           application/x-x509-ca-cert:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 证书不存在，需要先生成
 */
// 获取客户端证书（如果存在）
app.get('/cert/client.crt', (req, res) => {
  const certPath = path.join(__dirname, './cert/client.crt');
  
  if (!fs.existsSync(certPath)) {
    return res.status(404).json({ 
      error: 'Client certificate not found',
      message: '客户端证书不存在，请运行 generate_test_certs.sh 生成'
    });
  }
  
  res.setHeader('Content-Type', 'application/x-x509-ca-cert');
  res.setHeader('Content-Disposition', 'attachment; filename="client.crt"');
  res.sendFile(certPath);
});

/**
 * @swagger
 * /cert/client.key:
 *   get:
 *     summary: 下载客户端私钥
 *     description: 下载客户端私钥（无密码保护，仅用于测试）
 *     tags: [Certificates]
 *     responses:
 *       200:
 *         description: 客户端私钥文件
 *         content:
 *           application/x-pem-file:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 私钥不存在
 */
// 获取客户端私钥（无密码版本 - 测试用）
app.get('/cert/client.key', (req, res) => {
  const keyPath = path.join(__dirname, './cert/client.key');
  
  if (!fs.existsSync(keyPath)) {
    return res.status(404).json({ 
      error: 'Client key not found',
      message: '客户端私钥不存在，请运行 generate_test_certs.sh 生成'
    });
  }
  
  res.setHeader('Content-Type', 'application/x-pem-file');
  res.setHeader('Content-Disposition', 'attachment; filename="client.key"');
  res.sendFile(keyPath);
});

/**
 * @swagger
 * /cert/client_encrypted.key:
 *   get:
 *     summary: 下载加密客户端私钥
 *     description: 下载带密码保护的客户端私钥（密码：123456）
 *     tags: [Certificates]
 *     responses:
 *       200:
 *         description: 加密私钥文件
 *         content:
 *           application/x-pem-file:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 加密私钥不存在
 */
// 获取客户端加密私钥（带密码保护）
app.get('/cert/client_encrypted.key', (req, res) => {
  const keyPath = path.join(__dirname, './cert/client_encrypted.key');
  
  if (!fs.existsSync(keyPath)) {
    return res.status(404).json({ 
      error: 'Encrypted client key not found',
      message: '加密的客户端私钥不存在'
    });
  }
  
  res.setHeader('Content-Type', 'application/x-pem-file');
  res.setHeader('Content-Disposition', 'attachment; filename="client_encrypted.key"');
  res.sendFile(keyPath);
});

/**
 * @swagger
 * /cert/client.p12:
 *   get:
 *     summary: 下载客户端 PKCS#12 证书包
 *     description: |
 *       下载 PKCS#12 格式的客户端证书包（.p12/.pfx），包含客户端证书和私钥。
 *       可直接导入到浏览器、移动设备或应用程序中。
 *       
 *       **默认无密码**，可通过 password 参数设置密码
 *       
 *       **使用场景**:
 *       - 浏览器证书导入
 *       - iOS/Android 应用
 *       - OpenHarmony 应用
 *     tags: [Certificates]
 *     parameters:
 *       - in: query
 *         name: password
 *         schema:
 *           type: string
 *         description: 自定义 P12 密码（可选，默认无密码）
 *         example: "mypassword"
 *     responses:
 *       200:
 *         description: PKCS#12 证书包文件
 *         headers:
 *           X-P12-Password:
 *             schema:
 *               type: string
 *             description: P12 文件的密码（空字符串表示无密码）
 *         content:
 *           application/x-pkcs12:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 证书不存在
 *       500:
 *         description: 生成 P12 文件失败
 */
// 获取客户端 P12 证书包
app.get('/cert/client.p12', (req, res) => {
  const certPath = path.join(__dirname, './cert/client.crt');
  const keyPath = path.join(__dirname, './cert/client.key');
  const p12Path = path.join(__dirname, './cert/client.p12');
  const p12NoPassPath = path.join(__dirname, './cert/client_nopass.p12');
  
  // 检查证书和私钥是否存在
  if (!fs.existsSync(certPath) || !fs.existsSync(keyPath)) {
    return res.status(404).json({ 
      error: 'Client certificate or key not found',
      message: '客户端证书或私钥不存在',
      hint: '请运行 ./generate_test_certs.sh 生成证书'
    });
  }
  
  // 获取自定义密码，不传则为空（无密码）
  const password = req.query.password || '';
  const hasPassword = !!req.query.password;
  
  // 如果无密码版本 P12 文件已存在且没有自定义密码，直接返回
  if (fs.existsSync(p12NoPassPath) && !hasPassword) {
    res.setHeader('Content-Type', 'application/x-pkcs12');
    res.setHeader('Content-Disposition', 'attachment; filename="client.p12"');
    res.setHeader('X-P12-Password', '');
    return res.sendFile(p12NoPassPath);
  }
  
  // 生成 P12 文件
  const { execSync } = require('child_process');
  
  try {
    // 使用 openssl 将证书和私钥打包成 P12 格式
    const tempP12 = hasPassword ? 
      path.join(__dirname, `../../cert/client_${Date.now()}.p12`) : 
      p12NoPassPath;
    
    // 检查是否存在 CA 证书
    const caPath = path.join(__dirname, '../../cert/ca.crt');
    const hasCaCert = fs.existsSync(caPath);
    
    // 构建 openssl 命令（包含 CA 证书链）
    let command = `openssl pkcs12 -export -out "${tempP12}" -inkey "${keyPath}" -in "${certPath}"`;
    if (hasCaCert) {
      command += ` -certfile "${caPath}"`;
    }
    // 使用 -passout pass: 设置密码，空密码时为 -passout pass:
    command += ` -passout pass:${password}`;
    
    execSync(command, { stdio: 'pipe' });
    
    // 发送文件
    res.setHeader('Content-Type', 'application/x-pkcs12');
    res.setHeader('Content-Disposition', 'attachment; filename="client.p12"');
    res.setHeader('X-P12-Password', password);
    
    res.sendFile(tempP12, (err) => {
      // 如果使用了临时文件（自定义密码），发送后删除
      if (hasPassword && fs.existsSync(tempP12)) {
        try {
          fs.unlinkSync(tempP12);
        } catch (e) {
          console.error('Failed to delete temp P12 file:', e);
        }
      }
      
      if (err) {
        console.error('Error sending P12 file:', err);
      }
    });
    
  } catch (error) {
    console.error('Error generating P12 file:', error);
    res.status(500).json({ 
      error: 'Failed to generate P12 file',
      message: 'P12 文件生成失败',
      details: error.message,
      hint: '请确保已安装 OpenSSL'
    });
  }
});

/**
 * @swagger
 * /cert/client_encrypted.p12:
 *   get:
 *     summary: 下载带密码的客户端 PKCS#12 证书包
 *     description: |
 *       下载带密码保护的 PKCS#12 格式客户端证书包（.p12/.pfx）。
 *       **专用于 4002 端口的双向认证测试**。
 *       
 *       **固定密码**: `123456`
 *       
 *       **使用场景**:
 *       - 测试带密码的客户端证书
 *       - 4002 端口双向认证
 *     tags: [Certificates]
 *     responses:
 *       200:
 *         description: 带密码的 PKCS#12 证书包文件
 *         headers:
 *           X-P12-Password:
 *             schema:
 *               type: string
 *             description: P12 文件的密码（固定为 123456）
 *         content:
 *           application/x-pkcs12:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: 证书不存在
 *       500:
 *         description: 生成 P12 文件失败
 */
// 获取带密码的客户端 P12 证书包（专用于 4002 端口，密码: 123456）
app.get('/cert/client_encrypted.p12', (req, res) => {
  const certPath = path.join(__dirname, './cert/client.crt');
  const encryptedKeyPath = path.join(__dirname, './cert/client_encrypted.key');
  const p12EncryptedPath = path.join(__dirname, './cert/client_encrypted.p12');
  
  // 检查证书和加密私钥是否存在
  if (!fs.existsSync(certPath) || !fs.existsSync(encryptedKeyPath)) {
    return res.status(404).json({ 
      error: 'Client certificate or encrypted key not found',
      message: '客户端证书或加密私钥不存在',
      hint: '请运行 ./generate_test_certs.sh 或 ./cloud-deploy.sh 生成证书'
    });
  }
  
  // 固定密码为 123456
  const password = '123456';
  
  // 如果带密码的 P12 文件已存在，直接返回
  if (fs.existsSync(p12EncryptedPath)) {
    res.setHeader('Content-Type', 'application/x-pkcs12');
    res.setHeader('Content-Disposition', 'attachment; filename="client_encrypted.p12"');
    res.setHeader('X-P12-Password', password);
    return res.sendFile(p12EncryptedPath);
  }
  
  // 生成带密码的 P12 文件
  const { execSync } = require('child_process');
  
  try {
    // 检查是否存在 CA 证书
    const caPath = path.join(__dirname, '../../cert/ca.crt');
    const hasCaCert = fs.existsSync(caPath);
    
    // 构建 openssl 命令
    // 使用加密的私钥 client_encrypted.key，需要 -passin 读取私钥密码
    let command = `openssl pkcs12 -export -out "${p12EncryptedPath}" -inkey "${encryptedKeyPath}" -passin pass:${password} -in "${certPath}"`;
    if (hasCaCert) {
      command += ` -certfile "${caPath}"`;
    }
    command += ` -passout pass:${password}`;
    
    execSync(command, { stdio: 'pipe' });
    
    // 发送文件
    res.setHeader('Content-Type', 'application/x-pkcs12');
    res.setHeader('Content-Disposition', 'attachment; filename="client_encrypted.p12"');
    res.setHeader('X-P12-Password', password);
    res.sendFile(p12EncryptedPath);
    
  } catch (error) {
    console.error('Error generating encrypted P12 file:', error);
    res.status(500).json({ 
      error: 'Failed to generate encrypted P12 file',
      message: '带密码的 P12 文件生成失败',
      details: error.message,
      hint: '请确保已安装 OpenSSL 且 client_encrypted.key 存在'
    });
  }
});

/**
 * @swagger
 * /cert/client-bundle:
 *   get:
 *     summary: 一键获取所有证书
 *     description: 获取客户端双向认证所需的所有证书（JSON格式）
 *     tags: [Certificates]
 *     responses:
 *       200:
 *         description: 证书包（包含 ca.crt, client.crt, client.key）
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 message:
 *                   type: string
 *                   example: 客户端证书包（双向认证所需）
 *                 files:
 *                   type: object
 *                   properties:
 *                     ca_crt:
 *                       type: string
 *                       description: CA证书内容
 *                     client_crt:
 *                       type: string
 *                       description: 客户端证书内容
 *                     client_key:
 *                       type: string
 *                       description: 客户端私钥内容
 *                 usage:
 *                   type: object
 *                 download_urls:
 *                   type: object
 *                 security_note:
 *                   type: string
 *       404:
 *         description: 部分证书缺失
 */
// 一键下载客户端所需的所有证书（打包）
app.get('/cert/client-bundle', (req, res) => {
  const certDir = path.join(__dirname, '../../cert');
  const files = {
    'ca.crt': path.join(certDir, 'server.crt'),
    'client.crt': path.join(certDir, 'client.crt'),
    'client.key': path.join(certDir, 'client.key')
  };
  
  // 检查所有文件是否存在
  const missing = [];
  for (const [name, filePath] of Object.entries(files)) {
    if (!fs.existsSync(filePath)) {
      missing.push(name);
    }
  }
  
  if (missing.length > 0) {
    return res.status(404).json({ 
      error: 'Some certificates are missing',
      message: '部分证书文件不存在',
      missing: missing,
      hint: '请运行 ./generate_test_certs.sh 生成完整证书'
    });
  }
  
  // 返回 JSON 格式的证书内容
  res.json({
    message: '客户端证书包（双向认证所需）',
    files: {
      ca_crt: fs.readFileSync(files['ca.crt'], 'utf8'),
      client_crt: fs.readFileSync(files['client.crt'], 'utf8'),
      client_key: fs.readFileSync(files['client.key'], 'utf8')
    },
    usage: {
      ca_crt: '用于验证服务器证书',
      client_crt: '客户端证书（双向认证）',
      client_key: '客户端私钥（双向认证）'
    },
    download_urls: {
      ca_crt: '/cert/ca.crt',
      client_crt: '/cert/client.crt',
      client_key: '/cert/client.key'
    },
    security_note: '⚠️ 私钥文件请妥善保管，不要分享给他人'
  });
});

/**
 * @swagger
 * /cert/list:
 *   get:
 *     summary: 查看证书列表
 *     description: 获取所有证书文件的列表和状态信息
 *     tags: [Certificates]
 *     responses:
 *       200:
 *         description: 证书列表
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 message:
 *                   type: string
 *                   example: 证书文件列表
 *                 baseUrl:
 *                   type: string
 *                   example: http://localhost:4000
 *                 certificates:
 *                   type: array
 *                   items:
 *                     type: object
 *                     properties:
 *                       filename:
 *                         type: string
 *                       exists:
 *                         type: boolean
 *                       downloadUrl:
 *                         type: string
 *                       size:
 *                         type: number
 *                       modified:
 *                         type: string
 *                         format: date-time
 *                 note:
 *                   type: string
 */
// 证书列表和信息
app.get('/cert/list', (req, res) => {
  const certDir = path.join(__dirname, '../../cert');
  const certFiles = ['server.crt', 'server.key', 'client.crt', 'client.key', 'client_encrypted.key'];
  
  const certInfo = certFiles.map(file => {
    const filePath = path.join(certDir, file);
    const exists = fs.existsSync(filePath);
    let info = {
      filename: file,
      exists: exists,
      downloadUrl: exists ? `/cert/${file}` : null
    };
    
    if (exists) {
      const stats = fs.statSync(filePath);
      info.size = stats.size;
      info.modified = stats.mtime.toISOString();
    }
    
    return info;
  });
  
  res.json({
    message: '证书文件列表',
    baseUrl: `http://${req.headers.host}`,
    certificates: certInfo,
    note: 'server.crt 同时作为自签名 CA 证书使用'
  });
});

// ==================== Cache-Control 端点（合并自 cache-test-server）====================

/**
 * @swagger
 * /health:
 *   get:
 *     summary: 健康检查
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: 服务器健康状态
 */
app.get('/health', (req, res) => {
  res.json({
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime()
  });
});

/**
 * @swagger
 * /get:
 *   get:
 *     summary: 基本 GET 请求
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: 请求信息
 */
app.get('/get', (req, res) => {
  res.json({
    args: req.query,
    headers: req.headers,
    origin: req.ip,
    url: req.originalUrl
  });
});

/**
 * @swagger
 * /post:
 *   post:
 *     summary: POST 请求
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: POST 请求信息
 */
app.post('/post', (req, res) => {
  res.json({
    args: req.query,
    data: req.body,
    headers: req.headers,
    json: req.body,
    origin: req.ip,
    url: req.originalUrl
  });
});

/**
 * @swagger
 * /cache/{seconds}:
 *   get:
 *     summary: 返回带 Cache-Control max-age 的响应
 *     tags: [Cache]
 *     parameters:
 *       - in: path
 *         name: seconds
 *         required: true
 *         schema:
 *           type: integer
 *         description: 缓存秒数
 *     responses:
 *       200:
 *         description: 带缓存控制的响应
 */
app.get('/cache/:seconds', (req, res) => {
  const seconds = parseInt(req.params.seconds, 10);
  
  if (isNaN(seconds) || seconds < 0) {
    return res.status(400).json({ error: 'Invalid seconds parameter' });
  }

  const content = JSON.stringify({
    cached: true,
    maxAge: seconds,
    message: `This response should be cached for ${seconds} seconds`
  });
  const etag = `"${crypto.createHash('md5').update(content).digest('hex')}"`;
  
  const ifNoneMatch = req.headers['if-none-match'];

  res.set({
    'Cache-Control': `public, max-age=${seconds}`,
    'Content-Type': 'application/json',
    'ETag': etag
  });

  if (ifNoneMatch === etag || ifNoneMatch === etag.replace(/"/g, '')) {
    console.log(`  → 304 Not Modified (ETag matched: ${etag})`);
    return res.status(304).end();
  }

  res.json({
    cached: true,
    maxAge: seconds,
    timestamp: new Date().toISOString(),
    message: `This response should be cached for ${seconds} seconds`
  });
});

/**
 * @swagger
 * /response-headers:
 *   get:
 *     summary: 自定义响应头
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: 带自定义响应头的响应
 */
app.get('/response-headers', (req, res) => {
  for (const [key, value] of Object.entries(req.query)) {
    res.set(key, value);
  }

  res.json({
    headers: req.query,
    timestamp: new Date().toISOString()
  });
});

/**
 * @swagger
 * /etag/{etag}:
 *   get:
 *     summary: 返回带 ETag 的响应，支持 If-None-Match
 *     tags: [Cache]
 *     parameters:
 *       - in: path
 *         name: etag
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: ETag 响应
 *       304:
 *         description: Not Modified
 */
app.get('/etag/:etag', (req, res) => {
  const etag = req.params.etag;
  const ifNoneMatch = req.headers['if-none-match'];

  res.set('ETag', `"${etag}"`);

  if (ifNoneMatch === `"${etag}"` || ifNoneMatch === etag) {
    console.log(`  → 304 Not Modified (ETag matched: ${etag})`);
    return res.status(304).end();
  }

  res.json({
    etag: etag,
    timestamp: new Date().toISOString(),
    message: 'ETag response'
  });
});

/**
 * @swagger
 * /last-modified/{timestamp}:
 *   get:
 *     summary: 返回带 Last-Modified 的响应
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: Last-Modified 响应
 *       304:
 *         description: Not Modified
 */
app.get('/last-modified/:timestamp?', (req, res) => {
  const lastModified = req.params.timestamp 
    ? new Date(parseInt(req.params.timestamp, 10))
    : new Date(Date.now() - 3600000);

  const ifModifiedSince = req.headers['if-modified-since'];

  res.set('Last-Modified', lastModified.toUTCString());

  if (ifModifiedSince && new Date(ifModifiedSince) >= lastModified) {
    console.log(`  → 304 Not Modified (Last-Modified matched)`);
    return res.status(304).end();
  }

  res.json({
    lastModified: lastModified.toISOString(),
    timestamp: new Date().toISOString(),
    message: 'Last-Modified response'
  });
});

/**
 * @swagger
 * /delay/{seconds}:
 *   get:
 *     summary: 延迟响应
 *     tags: [Cache]
 *     parameters:
 *       - in: path
 *         name: seconds
 *         required: true
 *         schema:
 *           type: integer
 *         description: 延迟秒数 (0-10)
 *     responses:
 *       200:
 *         description: 延迟后的响应
 */
app.get('/delay/:seconds', async (req, res) => {
  const seconds = parseInt(req.params.seconds, 10);
  
  if (isNaN(seconds) || seconds < 0 || seconds > 10) {
    return res.status(400).json({ error: 'Invalid delay (0-10 seconds)' });
  }

  console.log(`  → Delaying ${seconds} seconds...`);
  await new Promise(resolve => setTimeout(resolve, seconds * 1000));

  res.set('Cache-Control', 'public, max-age=60');
  
  res.json({
    delayed: seconds,
    timestamp: new Date().toISOString()
  });
});

/**
 * @swagger
 * /uuid:
 *   get:
 *     summary: 返回随机 UUID
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: UUID 响应
 */
app.get('/uuid', (req, res) => {
  res.json({
    uuid: uuidv4(),
    timestamp: new Date().toISOString()
  });
});

/**
 * @swagger
 * /bytes/{n}:
 *   get:
 *     summary: 返回指定字节数的数据
 *     tags: [Cache]
 *     parameters:
 *       - in: path
 *         name: n
 *         required: true
 *         schema:
 *           type: integer
 *         description: 字节数 (0-1MB)
 *     responses:
 *       200:
 *         description: 二进制数据
 */
app.get('/bytes/:n', (req, res) => {
  const n = parseInt(req.params.n, 10);
  
  if (isNaN(n) || n < 0 || n > 1024 * 1024) {
    return res.status(400).json({ error: 'Invalid byte count (0-1MB)' });
  }

  const buffer = Buffer.alloc(n);
  for (let i = 0; i < n; i++) {
    buffer[i] = i % 256;
  }

  const etag = `"bytes-${n}"`;
  const ifNoneMatch = req.headers['if-none-match'];
  
  res.set('Cache-Control', 'public, max-age=60');
  res.set('ETag', etag);
  res.set('Content-Type', 'application/octet-stream');
  res.set('Content-Length', n.toString());
  
  if (ifNoneMatch === etag) {
    console.log(`  → 304 Not Modified (bytes ${n})`);
    return res.status(304).end();
  }
  
  res.send(buffer);
});

/**
 * @swagger
 * /redirect-to:
 *   get:
 *     summary: 重定向到指定 URL
 *     tags: [Cache]
 *     parameters:
 *       - in: query
 *         name: url
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       301:
 *         description: 重定向
 */
app.get('/redirect-to', (req, res) => {
  const url = req.query.url;
  
  if (!url) {
    return res.status(400).json({ error: 'Missing url parameter' });
  }

  console.log(`  → Redirecting to: ${url}`);
  res.redirect(301, url);
});

/**
 * @swagger
 * /redirect/{n}:
 *   get:
 *     summary: 相对重定向
 *     tags: [Cache]
 *     parameters:
 *       - in: path
 *         name: n
 *         required: true
 *         schema:
 *           type: integer
 *     responses:
 *       302:
 *         description: 重定向
 */
app.get('/redirect/:n', (req, res) => {
  const n = parseInt(req.params.n, 10);
  
  if (isNaN(n) || n <= 0) {
    return res.redirect('/get');
  }

  res.redirect(302, `/redirect/${n - 1}`);
});

/**
 * @swagger
 * /status/{code}:
 *   get:
 *     summary: 返回指定状态码
 *     tags: [Cache]
 *     parameters:
 *       - in: path
 *         name: code
 *         required: true
 *         schema:
 *           type: integer
 *     responses:
 *       default:
 *         description: 指定状态码的响应
 */
app.get('/status/:code', (req, res) => {
  const code = parseInt(req.params.code, 10);
  
  if (isNaN(code) || code < 100 || code > 599) {
    return res.status(400).json({ error: 'Invalid status code' });
  }

  res.status(code).json({
    code: code,
    message: `Status ${code}`,
    timestamp: new Date().toISOString()
  });
});

/**
 * @swagger
 * /vary:
 *   get:
 *     summary: 返回带 Vary 头的响应
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: 带 Vary 头的响应
 */
app.get('/vary', (req, res) => {
  const varyHeader = req.query.vary || 'Accept-Encoding';
  
  res.set('Vary', varyHeader);
  res.set('Cache-Control', 'public, max-age=60');
  
  res.json({
    vary: varyHeader,
    headers: req.headers,
    timestamp: new Date().toISOString()
  });
});

/**
 * @swagger
 * /gzip:
 *   get:
 *     summary: 返回可压缩的内容
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: 可压缩的文本数据
 */
app.get('/gzip', (req, res) => {
  const data = 'Hello '.repeat(1000);
  
  res.set('Content-Type', 'text/plain');
  res.set('Cache-Control', 'public, max-age=60');
  res.send(data);
});

/**
 * @swagger
 * /conditional:
 *   get:
 *     summary: 综合条件请求测试（同时支持 ETag 和 Last-Modified）
 *     tags: [Cache]
 *     responses:
 *       200:
 *         description: 条件请求响应
 *       304:
 *         description: Not Modified
 */
app.get('/conditional', (req, res) => {
  const etag = '"resource-v1"';
  const lastModified = new Date('2024-01-01T00:00:00Z');
  
  const ifNoneMatch = req.headers['if-none-match'];
  const ifModifiedSince = req.headers['if-modified-since'];

  res.set('ETag', etag);
  res.set('Last-Modified', lastModified.toUTCString());
  res.set('Cache-Control', 'public, max-age=60');

  if (ifNoneMatch === etag || 
      (ifModifiedSince && new Date(ifModifiedSince) >= lastModified)) {
    console.log(`  → 304 Not Modified`);
    return res.status(304).end();
  }

  res.json({
    etag: etag,
    lastModified: lastModified.toISOString(),
    timestamp: new Date().toISOString(),
    message: 'Conditional request resource'
  });
});

// ==================== 服务器启动 ====================

// 存储服务器实例供优雅关闭使用
let httpServer, httpsServer1, httpsServer2, httpsServer3, httpsServer4, http2Server;
let socksServer, httpProxyServer, httpProxyAuthServer;

// 1. HTTP 服务器 (端口 4000)
try {
  httpServer = http.createServer(app);
  
  httpServer.on('error', (err) => {
    logger.error('HTTP服务器错误', err);
    if (err.code === 'EADDRINUSE') {
      logger.error('端口 4000 已被占用');
    }
  });
  
  httpServer.on('clientError', (err, socket) => {
    logger.warn('HTTP客户端错误', { error: err.message });
    if (!socket.destroyed) {
      socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
    }
  });
  
  httpServer.listen(4000, () => {
    logger.info('✅ HTTP Server running on http://0.0.0.0:4000');
  });
} catch (err) {
  logger.error('HTTP服务器启动失败', err);
}

// 2. HTTPS 基础服务器 (端口 4001)
try {
  const certPath = path.join(__dirname, './cert/server.crt');
  const keyPath = path.join(__dirname, './cert/server.key');
  
  if (!fs.existsSync(certPath) || !fs.existsSync(keyPath)) {
    logger.warn('HTTPS证书不存在，跳过端口 4001');
  } else {
    const httpsOptions1 = {
      key: fs.readFileSync(keyPath),
      cert: fs.readFileSync(certPath)
    };
    httpsServer1 = https.createServer(httpsOptions1, app);
    
    httpsServer1.on('error', (err) => {
      logger.error('HTTPS服务器错误 (4001)', err);
      if (err.code === 'EADDRINUSE') {
        logger.error('端口 4001 已被占用');
      }
    });
    
    httpsServer1.on('clientError', (err, socket) => {
      logger.warn('HTTPS客户端错误 (4001)', { error: err.message });
      if (!socket.destroyed) {
        socket.end();
      }
    });
    
    httpsServer1.listen(4001, () => {
      logger.info('✅ HTTPS Server (basic) running on https://0.0.0.0:4001');
    });
  }
} catch (err) {
  logger.error('HTTPS服务器启动失败 (4001)', err);
}

// 3. HTTPS 双向认证 (端口 4002)
// 注意：这里验证客户端证书，但客户端私钥密码是在客户端配置的，不是服务器端
try {
  const certPath = path.join(__dirname, './cert/server.crt');
  const keyPath = path.join(__dirname, './cert/server.key');
  const caPath = path.join(__dirname, './cert/ca.crt');
  
  if (!fs.existsSync(certPath) || !fs.existsSync(keyPath) || !fs.existsSync(caPath)) {
    logger.warn('HTTPS双向认证证书不存在，跳过端口 4002');
  } else {
    const httpsOptions2 = {
      key: fs.readFileSync(keyPath),
      cert: fs.readFileSync(certPath),
      ca: fs.readFileSync(caPath),
      requestCert: true,       // 要求客户端提供证书
      rejectUnauthorized: true // 拒绝无效的客户端证书
    };
    httpsServer2 = https.createServer(httpsOptions2, app);
    
    httpsServer2.on('error', (err) => {
      logger.error('HTTPS双向认证服务器错误 (4002)', err);
    });
    
    httpsServer2.on('clientError', (err, socket) => {
      logger.warn('HTTPS双向认证客户端错误 (4002)', { error: err.message });
      if (!socket.destroyed) {
        socket.end();
      }
    });
    
    httpsServer2.listen(4002, () => {
      logger.info('✅ HTTPS Server (mutual TLS) running on https://0.0.0.0:4002');
    });
  }
} catch (err) {
  logger.error('HTTPS双向认证服务器启动失败 (4002)', err);
}

// 4. HTTPS 双向认证无密码 (端口 4003)
try {
  const certPath = path.join(__dirname, './cert/server.crt');
  const keyPath = path.join(__dirname, './cert/server.key');
  const caPath = path.join(__dirname, './cert/ca.crt');
  
  if (!fs.existsSync(certPath) || !fs.existsSync(keyPath) || !fs.existsSync(caPath)) {
    logger.warn('HTTPS双向认证证书不存在，跳过端口 4003');
  } else {
    const httpsOptions3 = {
      key: fs.readFileSync(keyPath),
      cert: fs.readFileSync(certPath),
      ca: fs.readFileSync(caPath),
      requestCert: true,
      rejectUnauthorized: true
    };
    httpsServer3 = https.createServer(httpsOptions3, app);
    
    httpsServer3.on('error', (err) => {
      logger.error('HTTPS双向认证服务器错误 (4003)', err);
    });
    
    httpsServer3.on('clientError', (err, socket) => {
      logger.warn('HTTPS双向认证客户端错误 (4003)', { error: err.message });
      if (!socket.destroyed) {
        socket.end();
      }
    });
    
    httpsServer3.listen(4003, () => {
      logger.info('✅ HTTPS Server (mutual auth no password) running on https://0.0.0.0:4003');
    });
  }
} catch (err) {
  logger.error('HTTPS双向认证服务器启动失败 (4003)', err);
}

// 5. HTTPS TLS 1.2 (端口 4004)
try {
  const certPath = path.join(__dirname, './cert/server.crt');
  const keyPath = path.join(__dirname, './cert/server.key');
  
  if (!fs.existsSync(certPath) || !fs.existsSync(keyPath)) {
    logger.warn('HTTPS TLS 1.2证书不存在，跳过端口 4004');
  } else {
    const httpsOptions4 = {
      key: fs.readFileSync(keyPath),
      cert: fs.readFileSync(certPath),
      minVersion: 'TLSv1.2',
      maxVersion: 'TLSv1.2'
    };
    httpsServer4 = https.createServer(httpsOptions4, app);
    
    httpsServer4.on('error', (err) => {
      logger.error('HTTPS TLS 1.2服务器错误 (4004)', err);
    });
    
    httpsServer4.on('clientError', (err, socket) => {
      logger.warn('HTTPS TLS 1.2客户端错误 (4004)', { error: err.message });
      if (!socket.destroyed) {
        socket.end();
      }
    });
    
    httpsServer4.listen(4004, () => {
      logger.info('✅ HTTPS Server (TLS 1.2) running on https://0.0.0.0:4004');
    });
  }
} catch (err) {
  logger.error('HTTPS TLS 1.2服务器启动失败 (4004)', err);
}

// 6. HTTP/2 over TLS (端口 4005)
try {
  const certPath = path.join(__dirname, './cert/server.crt');
  const keyPath = path.join(__dirname, './cert/server.key');
  
  if (!fs.existsSync(certPath) || !fs.existsSync(keyPath)) {
    logger.warn('HTTP/2证书不存在，跳过端口 4005');
  } else {
    const http2Options = {
      key: fs.readFileSync(keyPath),
      cert: fs.readFileSync(certPath),
      allowHTTP1: true // 允许降级到 HTTP/1.1
    };
    http2Server = http2.createSecureServer(http2Options, app);
    
    http2Server.on('error', (err) => {
      logger.error('HTTP/2服务器错误 (4005)', err);
    });
    
    http2Server.on('sessionError', (err) => {
      logger.warn('HTTP/2会话错误 (4005)', { error: err.message });
    });
    
    http2Server.listen(4005, () => {
      logger.info('✅ HTTP/2 Server running on https://0.0.0.0:4005');
    });
  }
} catch (err) {
  logger.error('HTTP/2服务器启动失败 (4005)', err);
}

// ==================== 全局错误处理 ====================

// 未捕获的异常 - 记录但不退出
process.on('uncaughtException', (err) => {
  logger.error('未捕获的异常（已恢复）', {
    error: err.message,
    stack: err.stack,
    name: err.name
  });
  
  // 不再退出进程，让服务器继续运行
  // process.exit(1); // 移除这行
});

// 未处理的 Promise 拒绝 - 记录但不退出
process.on('unhandledRejection', (reason, promise) => {
  logger.error('未处理的Promise拒绝（已恢复）', {
    reason: reason instanceof Error ? reason.message : reason,
    stack: reason instanceof Error ? reason.stack : undefined,
    promise: promise.toString()
  });
  
  // 不再退出进程
  // process.exit(1); // 移除这行
});

// 进程警告
process.on('warning', (warning) => {
  logger.warn('进程警告', {
    name: warning.name,
    message: warning.message,
    stack: warning.stack
  });
});

logger.info('🚀 OHOS Axios Test Server Started');
logger.info('📝 Note: Some HTTPS servers may fail if certificates are not available');

// ==================== 代理服务器功能 ====================

/**
 * SOCKS5 协议处理器（带用户名密码认证）
 * 默认用户名: socks5user
 * 默认密码: socks5pass
 */
function createSOCKS5Server(port, requireAuth = true, username = 'socks5user', password = 'socks5pass') {
  const server = net.createServer((clientSocket) => {
    logger.debug(`[SOCKS5:${port}] New connection from ${clientSocket.remoteAddress}:${clientSocket.remotePort}`);
    
    let state = 'handshake';
    let targetSocket = null;
    let authenticated = false;

    // 数据中继函数
    function relayData(source, dest, label) {
      source.on('data', (data) => {
        if (!dest.destroyed) {
          dest.write(data);
        }
      });
      
      source.on('error', (err) => {
        logger.warn(`[SOCKS5:${port}] ${label} error: ${err.message}`);
        source.destroy();
        if (dest && !dest.destroyed) dest.destroy();
      });
      
      source.on('end', () => {
        if (dest && !dest.destroyed) dest.end();
      });
    }

    clientSocket.on('data', (data) => {
      if (state === 'handshake') {
        // SOCKS5 握手: VER | NMETHODS | METHODS
        if (data.length < 2 || data[0] !== 0x05) {
          logger.error(`[SOCKS5:${port}] Invalid SOCKS version: ${data[0]}`);
          clientSocket.end();
          return;
        }
        
        // 检查客户端支持的认证方法
        const nmethods = data[1];
        const methods = Array.from(data.slice(2, 2 + nmethods));
        
        if (requireAuth) {
          // 需要认证：检查是否支持用户名密码认证 (0x02)
          if (methods.includes(0x02)) {
            // 响应：需要用户名密码认证 (0x02)
            clientSocket.write(Buffer.from([0x05, 0x02]));
            state = 'auth';
            logger.debug(`[SOCKS5:${port}] Requesting authentication`);
          } else {
            // 客户端不支持用户名密码认证
            logger.warn(`[SOCKS5:${port}] Client does not support username/password authentication`);
            clientSocket.write(Buffer.from([0x05, 0xFF])); // No acceptable methods
            clientSocket.end();
          }
        } else {
          // 不需要认证
          clientSocket.write(Buffer.from([0x05, 0x00]));
          state = 'request';
          authenticated = true;
        }
        
      } else if (state === 'auth') {
        // 用户名密码认证: VER | ULEN | UNAME | PLEN | PASSWD
        if (data.length < 3 || data[0] !== 0x01) {
          logger.error(`[SOCKS5:${port}] Invalid authentication version: ${data[0]}`);
          clientSocket.end();
          return;
        }
        
        const ulen = data[1];
        if (data.length < 2 + ulen + 1) {
          logger.error(`[SOCKS5:${port}] Invalid authentication data length`);
          clientSocket.end();
          return;
        }
        
        const receivedUsername = data.slice(2, 2 + ulen).toString();
        const plen = data[2 + ulen];
        const receivedPassword = data.slice(3 + ulen, 3 + ulen + plen).toString();
        
        // 验证用户名和密码
        if (receivedUsername === username && receivedPassword === password) {
          logger.info(`[SOCKS5:${port}] Authentication successful for user: ${receivedUsername}`);
          clientSocket.write(Buffer.from([0x01, 0x00])); // Success
          state = 'request';
          authenticated = true;
        } else {
          logger.warn(`[SOCKS5:${port}] Authentication failed for user: ${receivedUsername}`);
          clientSocket.write(Buffer.from([0x01, 0x01])); // Failure
          clientSocket.end();
        }
        
      } else if (state === 'request') {
        if (!authenticated) {
          logger.error(`[SOCKS5:${port}] Unauthenticated request`);
          clientSocket.end();
          return;
        }
        
      } else if (state === 'request') {
        // SOCKS5 连接请求: VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT
        if (data.length < 7 || data[0] !== 0x05) {
          logger.error(`[SOCKS5:${port}] Invalid request`);
          clientSocket.end();
          return;
        }
        
        const cmd = data[1];
        const atyp = data[3];
        
        if (cmd !== 0x01) { // 只支持 CONNECT
          console.error(`[SOCKS5:${port}] Unsupported command: ${cmd}`);
          clientSocket.write(Buffer.from([0x05, 0x07, 0x00, 0x01, 0, 0, 0, 0, 0, 0])); // Command not supported
          clientSocket.end();
          return;
        }
        
        let targetHost, targetPort, offset;
        
        if (atyp === 0x01) { // IPv4
          targetHost = `${data[4]}.${data[5]}.${data[6]}.${data[7]}`;
          targetPort = data.readUInt16BE(8);
          offset = 10;
        } else if (atyp === 0x03) { // Domain name
          const domainLength = data[4];
          targetHost = data.slice(5, 5 + domainLength).toString();
          targetPort = data.readUInt16BE(5 + domainLength);
          offset = 7 + domainLength;
        } else if (atyp === 0x04) { // IPv6
          targetHost = Array.from(data.slice(4, 20))
            .map((b, i) => (i % 2 === 0) ? b.toString(16).padStart(2, '0') : b.toString(16).padStart(2, '0'))
            .join('');
          targetPort = data.readUInt16BE(20);
          offset = 22;
        } else {
          console.error(`[SOCKS5:${port}] Unsupported address type: ${atyp}`);
          clientSocket.write(Buffer.from([0x05, 0x08, 0x00, 0x01, 0, 0, 0, 0, 0, 0])); // Address type not supported
          clientSocket.end();
          return;
        }
        
        console.log(`[SOCKS5:${port}] Connecting to ${targetHost}:${targetPort}`);
        
        // 连接到目标服务器
        targetSocket = net.connect(targetPort, targetHost, () => {
          console.log(`[SOCKS5:${port}] Connected to ${targetHost}:${targetPort}`);
          
          // 发送成功响应: VER | REP | RSV | ATYP | BND.ADDR | BND.PORT
          const response = Buffer.from([0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0]);
          clientSocket.write(response);
          
          state = 'relay';
          
          // 开始双向数据中继
          relayData(clientSocket, targetSocket, 'Client->Target');
          relayData(targetSocket, clientSocket, 'Target->Client');
        });
        
        targetSocket.on('error', (err) => {
          console.error(`[SOCKS5:${port}] Target connection error:`, err.message);
          if (state === 'request') {
            // 发送连接失败响应
            clientSocket.write(Buffer.from([0x05, 0x05, 0x00, 0x01, 0, 0, 0, 0, 0, 0])); // Connection refused
          }
          clientSocket.end();
        });
      }
    });
    
    clientSocket.on('error', (err) => {
      console.error(`[SOCKS5:${port}] Client socket error:`, err.message);
      if (targetSocket && !targetSocket.destroyed) targetSocket.destroy();
    });
    
    clientSocket.on('end', () => {
      if (targetSocket && !targetSocket.destroyed) targetSocket.end();
    });
  });
  
  server.listen(port, '0.0.0.0', () => {
    const authStr = requireAuth ? ` (需认证: ${username}/${password})` : ' (无认证)';
    logger.info(`✅ SOCKS5 Proxy Server running on 0.0.0.0:${port}${authStr}`);
  });
  
  server.on('error', (err) => {
    logger.error(`Failed to start SOCKS5 Proxy Server (${port})`, err);
  });
  
  return server;
}

/**
 * HTTP/HTTPS 代理处理器
 */
function createHTTPProxy(port, requireAuth = false) {
  const server = net.createServer((clientSocket) => {
    logger.debug(`[HTTP-Proxy:${port}] New connection from ${clientSocket.remoteAddress}:${clientSocket.remotePort}`);
    
    let buffer = Buffer.alloc(0);
    let headerParsed = false;
    let targetSocket = null;

    // 数据中继函数
    function relayData(source, dest, label) {
      source.on('data', (data) => {
        if (!dest.destroyed) {
          dest.write(data);
        }
      });
      
      source.on('error', (err) => {
        console.error(`[HTTP-Proxy:${port}] ${label} error:`, err.message);
        source.destroy();
        if (dest && !dest.destroyed) dest.destroy();
      });
      
      source.on('end', () => {
        if (dest && !dest.destroyed) dest.end();
      });
    }

    // 检查 HTTP Basic 认证
    function checkAuth(headers) {
      if (!requireAuth) return true;
      
      const authHeader = headers['proxy-authorization'];
      if (!authHeader) return false;
      
      const match = authHeader.match(/^Basic\s+(.+)$/i);
      if (!match) return false;
      
      const credentials = Buffer.from(match[1], 'base64').toString('utf8');
      return credentials === 'admin:123456';
    }

    clientSocket.on('data', (data) => {
      if (!headerParsed) {
        buffer = Buffer.concat([buffer, data]);
        
        const headerEndIndex = buffer.indexOf('\r\n\r\n');
        if (headerEndIndex === -1) return; // 继续等待完整的 header
        
        const headerStr = buffer.slice(0, headerEndIndex).toString();
        const lines = headerStr.split('\r\n');
        const requestLine = lines[0];
        
        // 解析请求头
        const headers = {};
        for (let i = 1; i < lines.length; i++) {
          const colonIndex = lines[i].indexOf(':');
          if (colonIndex !== -1) {
            const key = lines[i].slice(0, colonIndex).trim().toLowerCase();
            const value = lines[i].slice(colonIndex + 1).trim();
            headers[key] = value;
          }
        }
        
        // 认证检查
        if (!checkAuth(headers)) {
          console.log(`[HTTP-Proxy:${port}] Authentication failed`);
          clientSocket.write(
            'HTTP/1.1 407 Proxy Authentication Required\r\n' +
            'Proxy-Authenticate: Basic realm="Proxy"\r\n' +
            'Content-Length: 0\r\n' +
            '\r\n'
          );
          clientSocket.end();
          return;
        }
        
        const [method, urlStr] = requestLine.split(' ');
        
        // 处理 CONNECT 方法 (HTTPS 隧道)
        if (method === 'CONNECT') {
          const [targetHost, targetPort] = urlStr.split(':');
          
          console.log(`[HTTP-Proxy:${port}] CONNECT to ${targetHost}:${targetPort}`);
          
          targetSocket = net.connect(parseInt(targetPort) || 443, targetHost, () => {
            console.log(`[HTTP-Proxy:${port}] Tunnel established to ${targetHost}:${targetPort}`);
            
            // 发送连接成功响应
            clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
            
            // 开始双向数据中继
            relayData(clientSocket, targetSocket, 'Client->Target');
            relayData(targetSocket, clientSocket, 'Target->Client');
            
            headerParsed = true;
          });
          
          targetSocket.on('error', (err) => {
            console.error(`[HTTP-Proxy:${port}] Tunnel error:`, err.message);
            clientSocket.write('HTTP/1.1 502 Bad Gateway\r\n\r\n');
            clientSocket.end();
          });
          
        } else {
          // 处理普通 HTTP 请求
          const parsedUrl = url.parse(urlStr);
          const targetHost = parsedUrl.hostname || headers['host'];
          const targetPort = parsedUrl.port || 80;
          const targetPath = parsedUrl.path || '/';
          
          console.log(`[HTTP-Proxy:${port}] ${method} ${targetHost}:${targetPort}${targetPath}`);
          
          // 修改请求头（移除代理认证头，使用相对路径）
          const modifiedLines = [
            `${method} ${targetPath} HTTP/1.1`,
            `Host: ${targetHost}`,
            ...lines.slice(1).filter(line => {
              const lower = line.toLowerCase();
              return !lower.startsWith('proxy-authorization:') && !lower.startsWith('proxy-connection:');
            })
          ];
          
          const modifiedRequest = modifiedLines.join('\r\n') + '\r\n\r\n';
          const remainingData = buffer.slice(headerEndIndex + 4);
          
          targetSocket = net.connect(targetPort, targetHost, () => {
            console.log(`[HTTP-Proxy:${port}] Connected to ${targetHost}:${targetPort}`);
            
            // 发送修改后的请求
            targetSocket.write(modifiedRequest);
            if (remainingData.length > 0) {
              targetSocket.write(remainingData);
            }
            
            // 开始双向数据中继
            relayData(targetSocket, clientSocket, 'Target->Client');
            
            headerParsed = true;
          });
          
          targetSocket.on('error', (err) => {
            console.error(`[HTTP-Proxy:${port}] Target error:`, err.message);
            clientSocket.write('HTTP/1.1 502 Bad Gateway\r\n\r\n');
            clientSocket.end();
          });
          
          // 客户端后续数据直接转发
          clientSocket.on('data', (chunk) => {
            if (headerParsed && targetSocket && !targetSocket.destroyed) {
              targetSocket.write(chunk);
            }
          });
        }
      }
    });
    
    clientSocket.on('error', (err) => {
      logger.warn(`[HTTP-Proxy:${port}] Client socket error: ${err.message}`);
      if (targetSocket && !targetSocket.destroyed) targetSocket.destroy();
    });
    
    clientSocket.on('end', () => {
      if (targetSocket && !targetSocket.destroyed) targetSocket.end();
    });
  });
  
  server.listen(port, '0.0.0.0', () => {
    const authStr = requireAuth ? ' (with auth: admin/123456)' : ' (no auth)';
    logger.info(`✅ HTTP/HTTPS Proxy Server running on 0.0.0.0:${port}${authStr}`);
  });
  
  server.on('error', (err) => {
    logger.error(`Failed to start HTTP Proxy Server (${port})`, err);
  });
  
  return server;
}

// 启动代理服务器
try {
  // SOCKS5 代理 - 带认证（用户名: socks5user, 密码: socks5pass）
  socksServer = createSOCKS5Server(1080, true, 'socks5user', 'socks5pass');
  
  // HTTP 代理 - 无认证
  httpProxyServer = createHTTPProxy(8080, false);
  
  // HTTP 代理 - 需认证 (admin/123456)
  httpProxyAuthServer = createHTTPProxy(8081, true);
  
  logger.info('✅ All proxy servers started successfully');
} catch (err) {
  logger.error('代理服务器启动失败', err);
}

// ==================== 优雅关闭 ====================

const gracefulShutdown = (signal) => {
  logger.info(`收到 ${signal} 信号，准备优雅关闭...`);
  
  const servers = [
    httpServer,
    httpsServer1,
    httpsServer2,
    httpsServer3,
    httpsServer4,
    http2Server,
    socksServer,
    httpProxyServer,
    httpProxyAuthServer
  ].filter(s => s); // 过滤掉未创建的服务器
  
  let closed = 0;
  const total = servers.length;
  
  if (total === 0) {
    logger.info('没有运行中的服务器');
    process.exit(0);
  }
  
  servers.forEach(server => {
    try {
      server.close(() => {
        closed++;
        logger.info(`服务器已关闭 (${closed}/${total})`);
        if (closed === total) {
          logger.info('所有服务器已关闭');
          process.exit(0);
        }
      });
    } catch (err) {
      logger.error('关闭服务器时出错', err);
      closed++;
    }
  });
  
  // 强制关闭超时
  setTimeout(() => {
    logger.warn('强制关闭超时，立即退出');
    process.exit(1);
  }, 10000);
};

process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
